package cc.plumgo.ss.yo.entity;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.LayerManager;
import javax.microedition.lcdui.game.Sprite;

import cc.plumgo.j2me.utils.CustomCanvas;
import cc.plumgo.j2me.utils.CustomRole;
import cc.plumgo.ss.core.Constants;

public class Hero extends CustomRole {

	public static final int MAN_STOP = 0;
	public static final int MAN_WALK = 1;
	public static final int MAN_ATTACK = 2;
	public static final int MAN_ATTACKED = 3;
	public static final int MAN_DIE = 4;
	public static final int MAN_JUMP = 5;
	public static final int MAN_CROUCH = 6;

	private boolean upFlag = false;
	private boolean downFlag = false;
	private int jumpY;
	private int crouchY;
	private int awayX;
	private int awayY;
	private int awayDis;
	private boolean jumpFail;

	private int preState;
	private int lifeNum;
	
	private Image backImage;
	private Image bloodImage;
	private int bloodlen;
	private int scrWidth;
	private int scrHeight;
	
	public int getHeight() {
		return sprites[index].getHeight();
	}

	public int getX() {
		return sprites[index].getX();
	}

	public int getY() {
		return sprites[index].getY();
	}

	public Hero() {
		super(4);
		totalState = 7;
		state = MAN_STOP;
		try {
			sprites = new Sprite[totalState];
			Image img = null;

			for (int i = 0; i < totalState; i++) {
				img = Image.createImage(Constants.MAN_SPRITE_IMGS[i]);
				sprites[i] = new Sprite(img, Constants.MAN_SPRITE_W[i],
						Constants.MAN_SPRITE_H[i]);
			}
			
			backImage = Image.createImage(Constants.MAN_STATE_IMG);
			bloodImage = Image.createImage(Constants.MAN_BLOOD_IMG);
		} catch (Exception e) {
			e.printStackTrace();
		}
		initFrameNums();
		lifeNum = 3;
		awayX = 0;
		blood = Constants.MAN_BLOOD;
		scrWidth = CustomCanvas.canvas.getWidth();
		scrHeight = CustomCanvas.canvas.getHeight();
		bloodlen = getBloodLength();
	}

	public int getState() {
		return state;
	}

	public void setState(int state) {
		if (state < 0 || state >= totalState) {
			return;
		}
		preState = this.state;
		this.state = state;
	}

	public void input(int keyState) {
		savePosYState();
		switch (keyState) {
		case GameCanvas.KEY_NUM2: {// up
			upFlag = true;
			setState(MAN_JUMP);
			break;
		}
		case GameCanvas.KEY_NUM4: {// left
			setState(MAN_WALK);
			setDirect(DIR_LEFT);
			posX -= Constants.MAN_WALK_SPEED;
			break;
		}
		case GameCanvas.KEY_NUM6: {// right
			setState(MAN_WALK);
			setDirect(DIR_RIGHT);
			posX += Constants.MAN_WALK_SPEED;
			break;
		}
		case GameCanvas.KEY_NUM8: {// down
			downFlag = true;
			setState(MAN_CROUCH);
			break;
		}
		case GameCanvas.KEY_NUM5: {// attack
			setState(MAN_ATTACK);
			fire();
			break;
		}
		case GameCanvas.LEFT: {// menu
		}
		case GameCanvas.RIGHT: {// pause

		}
		}
	}

	public void logic() {
		super.logic();
		jumpAway();

		boolean moveFlag = true;
		for (index = 1; index < frameNums.length; index++) {
			if (frameNums[index] != -1) {
				moveFlag = false;
				break;
			}
		}
		
		if (moveFlag) {
			index = state;
			frameNums[index] = 0;
		} else {
			switch (state) {
			case MAN_JUMP: {
				if (upFlag) {
					if (posY - Constants.MAN_JUMP_Y_SPEED < jumpY
							- Constants.MAN_JUMP_HEIGHT) {
						upFlag = !upFlag;
					} else {
						posY -= Constants.MAN_JUMP_Y_SPEED;
						updateFrameNums(2);
					}
				} else {
					if (posY + Constants.MAN_JUMP_Y_SPEED > jumpY) {
						upFlag = !upFlag;
						updateLastFrame();
						return;
					} else {
						posY += Constants.MAN_JUMP_Y_SPEED;
						updateFrameNums(1);
					}
				}
				if (preState == MAN_WALK) {
					if (direct == DIR_LEFT) {
						posX -= Constants.MAN_JUMP_X_SPEED;
					} else if (direct == DIR_RIGHT) {
						posX += Constants.MAN_JUMP_X_SPEED;
					}
				}
				break;
			}
			case MAN_CROUCH: {
				if (downFlag) {
					if (posY + Constants.MAN_CROUCH_SPEED > crouchY
							+ Constants.MAN_CROUCH_HEIGHT) {
						downFlag = !downFlag;
					} else {
						posY += Constants.MAN_CROUCH_SPEED;
						updateFrameNums(1);
					}
				} else {
					if (posY - Constants.MAN_CROUCH_SPEED < crouchY) {
						downFlag = !downFlag;
						updateLastFrame();
						return;
					} else {
						posY -= Constants.MAN_CROUCH_SPEED;
						if (--frameNums[index] <= 0) {
							frameNums[index] = 0;
						}
					}
				}
				break;
			}

			case MAN_ATTACKED: {
				if (++frameNums[index] >= sprites[index]
						.getFrameSequenceLength()) {
					switch (direct) {
					case DIR_LEFT: {
						posX += Constants.MAN_ATTACKED_AWAY_DIS;
						break;
					}
					case DIR_RIGHT: {
						posX -= Constants.MAN_ATTACKED_AWAY_DIS;
						break;
					}
					}
					updateLastFrame();
					bloodlen = getBloodLength();
					return;
				}
				break;
			}
			case MAN_DIE: {
				if (++frameNums[index] >= sprites[index]
						.getFrameSequenceLength()) {
					updateLastFrame();
					if (--lifeNum < 0) {
						died = true;
					} else {
						setState(MAN_STOP);
						blood = Constants.MAN_BLOOD;
					}
					return;
				}
				break;
			}
			case MAN_ATTACK:
			case MAN_WALK: {
				if (++frameNums[index] >= sprites[index]
						.getFrameSequenceLength()) {
					updateLastFrame();
					return;
				}
			}
			}

		}
		updateSpriteDirect(index);
		updateFrameNums();
		updateAllPositions();

	}

	public void drawStateBar(Graphics g) {
		g.drawImage(backImage, 10, 0, 0);
		g.drawString(Integer.toString(bullet.bulletNums[1]), 94, 19, 0);
		g.drawString(Integer.toString(bullet.bulletNums[2]), 139, 19, 0);
		g.drawString(Integer.toString(bullet.bulletNums[3]), 185, 19, 0);
		g.drawString(Integer.toString(lifeNum), 145, 53, 0);
		g.setClip(73, 44, bloodlen, 5);
		g.drawImage(bloodImage, 73, 44, 0);
		g.setClip(0, 0, scrWidth, scrHeight);
	}
	
	private int getBloodLength() {
		return 112 * blood / Constants.MAN_BLOOD;
	}
	
	private void savePosYState() {
		jumpY = posY;
		crouchY = posY;
		upFlag = false;
		downFlag = false;
	}

	private void updateFrameNums(int coef) {
		int tmp = sprites[index].getFrameSequenceLength() / coef;
		if (++frameNums[index] >= tmp) {
			frameNums[index] = tmp - 1;
		}
	}

	private void updateLastFrame() {
		frameNums[index] = -1;
		setState(MAN_STOP);
		index = 0;
	}

	public boolean isStateLock() {
		return getState() == MAN_JUMP || getState() == MAN_CROUCH || awayDis != 0;
	}

	public void jumpAway() {
		if (awayDis != 0) {
			jumpFail = false;
			if (posY < Constants.MAN_JUMP_HEIGHT) {
				posY -= Constants.MAN_JUMP_AWAY_Y;
			}
			int tmpX = 0;
			if (awayDis > 0) {
				tmpX = posX - Constants.MAN_JUMP_AWAY_SPEED;
				posX = tmpX <= 0 ? 0 : tmpX;
				if (posX < awayX - Constants.MAN_JUMP_AWAY_DIS) {
					awayDis = 0;
					posY = awayY;
					hurt(Constants.MAN_JUMP_AWAY_HARM);
				}
			} else {
				tmpX = posX + Constants.MAN_JUMP_AWAY_SPEED;
				posX = tmpX >= Constants.SCENE_SIZ[0] ? Constants.SCENE_SIZ[0] : tmpX;
				if (posX > awayX + Constants.MAN_JUMP_AWAY_DIS) {
					awayDis = 0;
					posY = awayY;
					hurt(Constants.MAN_JUMP_AWAY_HARM);
				}
			}
			if (tmpX <= 0 || tmpX >= Constants.SCENE_SIZ[0]) {
				jumpFail = true;
			}
			return;
		} else {
			awayX = posX;
			awayY = posY;
		}
	}

	public boolean isJumpFail() {
		return jumpFail;
	}

	public void setAwayDis(int awayDis) {
		if (this.awayDis == 0) {
			this.awayDis = awayDis;
		}

	}

	public void setLayer(LayerManager layerMana) {
		super.setLayer(layerMana);
		bullet.setLayer(layerMana);
	}

	public void hurt(int drop) {
		blood -= drop;
		if (blood <= 0) {
			setState(MAN_DIE);
		} else {
			setState(MAN_ATTACKED);
		}
	}
	
	public void addLife() {
		lifeNum ++;
	}
	
	public void addBlood() {
		blood += 50;
		if (blood > 200) {
			blood = 200;
		}
	}
	
	public void addBullets(int base, int foot, int bask) {
		bullet.addBulletNums(base, foot, bask);
	}
}
